/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.debugger.jpda;
import java.beans.PropertyEditor;
import java.util.ResourceBundle;
import java.util.List;
import java.util.LinkedList;
import java.text.MessageFormat;
import javax.swing.SwingUtilities;
import javax.swing.JComponent;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.ClassUnloadRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.ClassUnloadEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.EventIterator;
import com.sun.jdi.event.StepEvent;
import org.openide.TopManager;
import org.openide.explorer.propertysheet.editors.ChoicePropertyEditor;
import org.openide.filesystems.FileObject;
import org.openide.text.Line;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.openide.util.NbBundle;
import org.openide.util.actions.SystemAction;
import org.netbeans.modules.debugger.jpda.util.*;
import org.netbeans.modules.debugger.support.CoreBreakpoint;
import org.netbeans.modules.debugger.support.StopEvent;
import org.netbeans.modules.debugger.support.StopAction;
import org.netbeans.modules.debugger.support.PrintAction;
import org.netbeans.modules.debugger.support.AbstractVariable;
import org.netbeans.modules.debugger.support.AbstractThread;
import org.netbeans.modules.debugger.support.CallStackFrame;
import org.netbeans.modules.debugger.support.actions.AddBreakpointAction;
/**
* Implementation of breakpoint on method.
*
* @author Jan Jancura
*/
public class ClassBreakpoint extends CoreBreakpoint.Event implements Executor, StopEvent {
// static ....................................................................................
/** Property name constant. */
public static final String PROP_TYPE = "type"; // NOI18N
/** Property name constant. */
public static final String PROP_CLASS_FILTER = "classFilter"; // NOI18N
/** Property name constant. */
public static final String PROP_EXCLUSION_FILTER = "exclusionFilter"; // NOI18N
/** Property type constant. */
public static final int TYPE_PREPARE = 1;
/** Property type constant. */
public static final int TYPE_UNLOAD = 2;
// variables ....................................................................................
/** Thread which stops on this breakpoint. */
private transient ThreadReference thread;
/** Stores all EventRequests produced by this Event. */
private Requestor requestor;
private int type = TYPE_PREPARE;
private boolean exclusionFilter = false;
private String classFilter = ((AddBreakpointAction)
SystemAction.get (AddBreakpointAction.class)).getCurrentClassName ();
private transient String action;
private transient String className;
// Event impl ......................................................................................
/**
* Returns the new instance of Breakpoint.Event.
*/
public CoreBreakpoint.Event getNewInstance () {
return new ClassBreakpoint ();
}
/**
* Sets breakpoint with specified properties.
*/
public boolean set () { //S ystem.out.println ("ClassBreakpoint.set TRY " + this + " in " + getDebugger () ); // NOI18N
JPDADebugger debugger = (JPDADebugger) getDebugger ();
if (debugger.virtualMachine == null) return false;
if ((getClassFilter () == null) || (getClassFilter ().trim ().length () < 1)) return false;
if (requestor == null) requestor = new Requestor (debugger.requestManager);
try {
requestor.removeRequests ();
if ((type & TYPE_PREPARE) != 0) {
ClassPrepareRequest cpr = debugger.requestManager.createClassPrepareRequest ();
cpr.setSuspendPolicy (ClassPrepareRequest.SUSPEND_ALL);
if (exclusionFilter)
cpr.addClassExclusionFilter (getClassFilter ());
else
cpr.addClassFilter (getClassFilter ());
debugger.operator.register (cpr, this);
requestor.add (cpr);
cpr.enable (); //S ystem.out.println ("ClassBreakpoint.set PREPARE " + exclusionFilter); // NOI18N
}
if ((type & TYPE_UNLOAD) != 0) {
ClassUnloadRequest cur = debugger.requestManager.createClassUnloadRequest ();
cur.setSuspendPolicy (ClassUnloadRequest.SUSPEND_ALL);
if (exclusionFilter)
cur.addClassExclusionFilter (getClassFilter ());
else
cur.addClassFilter (getClassFilter ());
debugger.operator.register (cur, this);
requestor.add (cur);
cur.enable (); //S ystem.out.println ("ClassBreakpoint.set UNLOAD " + exclusionFilter); // NOI18N
}
} catch (VMDisconnectedException e) {
}
return true;
}
/**
* Removes breakpoint.
*/
public void remove () { //S ystem.out.println ("ClassBreakpoint.remove " + this); // NOI18N
if (requestor != null)
requestor.removeRequests ();
}
/**
* Returns specific properties of this event.
*/
public Node.Property[] getProperties () {
final ResourceBundle bundle = NbBundle.getBundle (VariableBreakpoint.class);
return new Node.Property[] {
new PropertySupport.ReadWrite (
PROP_CLASS_FILTER,
String.class,
bundle.getString ("PROP_class_filter"),
bundle.getString ("HINT_class_filter")
) {
public Object getValue () throws IllegalArgumentException {
return getClassFilter ();
}
public void setValue (Object val) throws IllegalArgumentException {
setClassFilter (((String) val).trim ());
}
},
new PropertySupport.ReadWrite (
PROP_EXCLUSION_FILTER,
Boolean.TYPE,
bundle.getString ("PROP_class_exclusion_filter"),
bundle.getString ("HINT_class_exclusion_filter")
) {
public Object getValue () throws IllegalArgumentException {
return new Boolean (getExclusionFilter ());
}
public void setValue (Object val) throws IllegalArgumentException {
try {
setExclusionFilter (((Boolean) val).booleanValue ());
} catch (ClassCastException e) {
throw new IllegalArgumentException ();
}
}
},
new PropertySupport.ReadWrite (
PROP_TYPE,
Integer.TYPE,
bundle.getString ("PROP_class_type"),
bundle.getString ("HINT_class_type")
) {
public Object getValue () throws IllegalArgumentException {
return new Integer (getType ());
}
public void setValue (Object val) throws IllegalArgumentException {
try {
setType (((Integer) val).intValue ());
} catch (ClassCastException e) {
throw new IllegalArgumentException ();
}
}
public PropertyEditor getPropertyEditor () {
return new ChoicePropertyEditor (
new int[] {
TYPE_PREPARE,
TYPE_UNLOAD,
TYPE_PREPARE | TYPE_UNLOAD
},
new String[] {
bundle.getString ("CTL_Breakpoint_type_class_prepare"),
bundle.getString ("CTL_Breakpoint_type_class_unload"),
bundle.getString ("CTL_Breakpoint_type_class_both")
}
);
}
}
};
}
/**
* Returns line of breakpoint.
*/
public Line[] getLines () {
return null;
}
/**
* Returns name of type of this event.
*/
public String getTypeName () {
return "Class"; // NOI18N
}
/**
* Returns display name of this event.
*/
public String getTypeDisplayName () {
return NbBundle.getBundle (ClassBreakpoint.class).getString ("CTL_Class_event_type_name");
}
/**
* Returns display name of this instance of event. It will be used
* as the name of the breakpoint.
*/
public String getDisplayName () {
if (type == TYPE_PREPARE)
return new MessageFormat (
NbBundle.getBundle (ClassBreakpoint.class).getString ("CTL_Class_prepare_event_name")
).format (new Object[] {getClassFilter ()});
else
if (type == TYPE_UNLOAD)
return new MessageFormat (
NbBundle.getBundle (ClassBreakpoint.class).getString ("CTL_Class_unload_event_name")
).format (new Object[] {getClassFilter ()});
return new MessageFormat (
NbBundle.getBundle (ClassBreakpoint.class).getString ("CTL_Class_event_name")
).format (new Object[] {getClassFilter ()});
}
/**
* Returns name of icon.
*/
public String getIconBase () {
return "/org/netbeans/modules/debugger/resources/breakpointOnClass"; // NOI18N
}
/**
* Returns customizer visual component.
*/
public JComponent getCustomizer () {
return new ClassBreakpointPanel (this);
}
/**
* Returns actions available specially for this version of event.
*/
public CoreBreakpoint.Action[] getBreakpointActions () {
CoreBreakpoint.Action[] myActions = new CoreBreakpoint.Action[] {
new StopAction (),
new ClassPrintAction (),
};
CoreBreakpoint.Action[] actions = new CoreBreakpoint.Action [super.getBreakpointActions ().length + myActions.length];
System.arraycopy (super.getBreakpointActions (), 0, actions, 0, super.getBreakpointActions ().length);
System.arraycopy (myActions, 0, actions, super.getBreakpointActions ().length, myActions.length);
return actions;
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractThread getThread () {
if (thread == null) return null;
JPDADebugger debugger = (JPDADebugger) getDebugger ();
return debugger.threadManager.getThread (thread);
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public CallStackFrame[] getCallStack () {
return getThread ().getCallStack ();
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractVariable getVariable () {
return null;
}
// interface Executor .....................................................................
/**
* Executes breakpoint hit event.
*/
public void exec (com.sun.jdi.event.Event event) { //S ystem.out.println ("ClassBreakpoint.exec! " + this + " : " + event); // NOI18N
if (event instanceof ClassPrepareEvent) {
thread = ((ClassPrepareEvent) event).thread ();
action = NbBundle.getBundle (ThreadBreakpoint.class).getString ("CTL_Prepared");
className = ((ClassPrepareEvent) event).referenceType ().name ();
} else {
action = NbBundle.getBundle (ThreadBreakpoint.class).getString ("CTL_Unload");
className = ((ClassUnloadEvent) event).className ();
}
perform ();
}
// StopEvent impl ......................................................................................
/**
* Performs stop action.
*/
public void stop (boolean stop) {
((JPDADebugger) getDebugger ()).stop (stop, getThread ());
}
// other methods ......................................................................................
/**
* Returns type of breakpoint.
*/
public int getType () {
return type;
}
/**
* Sets type of breakpoint.
*/
public void setType (int type) {
if (type == this.type) return;
if ((type & (TYPE_PREPARE | TYPE_UNLOAD)) == 0)
throw new IllegalArgumentException ();
int old = type;
this.type = type;
firePropertyChange (PROP_TYPE, new Integer (old), new Integer (type));
}
/**
* Setter of property exclusion filter.
*/
public boolean getExclusionFilter () {
return exclusionFilter;
}
/**
* Getter of property exclusion filter.
*/
public void setExclusionFilter (boolean exclusionFilter) {
if (exclusionFilter == this.exclusionFilter) return;
boolean old = exclusionFilter;
this.exclusionFilter = exclusionFilter;
firePropertyChange (PROP_EXCLUSION_FILTER, new Boolean (old), new Boolean (exclusionFilter));
}
/**
* Returns class filter.
*/
public String getClassFilter () {
return classFilter;
}
/**
* Sets class filter.
*/
public void setClassFilter (String classFilter) {
if (this.classFilter == null) {
if (classFilter == null) return;
} else
if ((classFilter != null) && classFilter.equals (this.classFilter)) return;
String old = classFilter;
this.classFilter = classFilter;
firePropertyChange (PROP_CLASS_FILTER, old, classFilter);
}
public String toString () {
return "JPDAClassBreakpoint " + getClassFilter (); // NOI18N
}
// innerclasses ......................................................................................
class ClassPrintAction extends PrintAction {
/**
* Creates the new Thrad Print action with default text.
*/
ClassPrintAction () {
super (
NbBundle.getBundle (ClassBreakpoint.class).getString ("CTL_Class_print_name")
);
}
/**
* Returns new initialized instance of Thrad Print action.
*/
protected CoreBreakpoint.Action getNewInstance () {
return new ClassPrintAction ();
}
/**
* Resolving special tags:
* className name of the class the breakpoint is reached in
* action name of action
*/
protected void resolveTag (String tag, CoreBreakpoint.Event event, StringBuffer sb) {
if (tag.equals ("className")) // NOI18N
sb.append (((ClassBreakpoint) event).className);
else
if (tag.equals ("action")) // NOI18N
sb.append (((ClassBreakpoint) event).action);
else
super.resolveTag (tag, event, sb);
}
}
}
/*
* Log
* 9 Gandalf-post-FCS1.7.4.0 3/28/00 Daniel Prusa
* 8 Gandalf 1.7 1/14/00 Daniel Prusa NOI18N
* 7 Gandalf 1.6 1/13/00 Daniel Prusa NOI18N
* 6 Gandalf 1.5 1/4/00 Jan Jancura Use trim () on user
* input.
* 5 Gandalf 1.4 11/8/99 Jan Jancura Somma classes renamed
* 4 Gandalf 1.3 11/5/99 Jan Jancura Empty values support
* 3 Gandalf 1.2 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 2 Gandalf 1.1 9/28/99 Jan Jancura
* 1 Gandalf 1.0 9/28/99 Jan Jancura
* $
*/